/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package beans.managed;

import beans.custom.GameController;
import beans.ejb.NflplayerFacade;
import beans.ejb.NflplayerseasonstatFacade;
import beans.ejb.NflteamFacade;
import crowler.CrowlerEssentials;
import entities.Nflplayer;
import entities.Nflplayerseasonstat;
import entities.NflplayerseasonstatPK;
import entities.Nflteam;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 *
 * @author The Lunatics Season /{format}/LastCompletedSeason?key={licensekey}
 * /{format}/CurrentSeason?key={licensekey}
 * /{format}/UpcomingSeason?key={licensekey} Week
 * /{format}/LastCompletedWeek?key={licensekey}
 * /{format}/CurrentWeek?key={licensekey}
 * /{format}/UpcomingWeek?key={licensekey} Teams
 * /{format}/Teams/{season}?key={licensekey}Page 2 of 5 Scores and Schedules
 * /{format}/Schedules/{season}?key={licensekey}
 * /{format}/Byes/{season}?key={licensekey}
 * /{format}/Scores/{season}?key={licensekey} Team Stats and Standings
 * /{format}/TeamGameStats/{season}/{week}?key={licensekey}
 * /{format}/TeamSeasonStats/{season}?key={licensekey}
 * /{format}/Standings/{season}?key={licensekey} Player Rosters and Depth Charts
 * /{format}/Players/{team}?key={licensekey}
 * /{format}/FreeAgents?key={licensekey} Player Stats
 * /{format}/PlayerGameStatsByTeam/{season}/{week}/{team}?key={licensekey}
 * /{format}/PlayerSeasonStatsByTeam/{season}/{team}?key={licensekey}
 * /{format}/PlayerGameStatsByPlayerID/{season}/{week}/{playerid}?key={licensekey}
 * /{format}/PlayerSeasonStatsByPlayerID/{season}/{playerid}?key={licensekey}
 * League Leaders
 * /{format}/SeasonLeagueLeaders/{season}/{position}/{column}?key={licensekey}
 * /{format}/GameLeagueLeaders/{season}/{week}/{position}/{column}?key={licensekey}
 * Fantasy Defense
 * /{format}/FantasyDefenseByGame/{season}/{week}?key={licensekey}
 * /{format}/FantasyDefenseBySeason/{season}?key={licensekey} Injuries
 * /{format}/Injuries/{season}/{week}?key={licensekey}
 * /{format}/Injuries/{season}/{week}/{team}?key={licensekey} Breaking News
 * /{format}/News?key={licensekey} Live Web Methods Live web methods are
 * available for clients with an Enterprise Licens
 */
@ManagedBean
@ApplicationScoped
public class Crowler extends CrowlerEssentials {

    private String tableName = "teamTable";
    @EJB
    private NflteamFacade teamFacade;
    @EJB
    private NflplayerFacade playerFacade;
    @EJB
    private NflplayerseasonstatFacade playerSeasonFacade;
    /**
     * 1984-08-24T00:00:00
     */
    private static final SimpleDateFormat dateFormat =
            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

    /**
     * Creates a new instance of Crowler
     */
    public Crowler() throws ParserConfigurationException {
        System.err.println("Crowler Construction");
        docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    }

    private void queryCurrentSeason() throws IOException {
        URL url = new URL(TESTURL + "/xml/CurrentSeason/?key=" + licensekey);
        Document doc = request(url, "GET", null);
    }

    public String queryTeams() throws IOException {
        System.err.println("getTeams:" + season);
//        http://api.nfldata.com/api.svc/xml/Teams/2011?key=c7fb0f65-ccb4-4965-bbb9-4cecd0890e10
        URL url = new URL(TESTURL + "/xml/Teams/" + season + "?key=" + licensekey);

        Document doc = request(url, "GET", null);

        teams = new ArrayList();
        NodeList nodes = doc.getElementsByTagName("Team");
        for (int i = 0; i < nodes.getLength(); i++) {
            Nflteam team = createNflteamFromElement((Element) nodes.item(i));
            team.setId(i + 1);
            team.setFullname(team.getHometown() + " " + team.getMascot());
            teams.add(team);
        }
        return returnPage;
    }

    public String queryAllPlayersFromLocalDBToRemoveOtherPositions() {
        players = playerFacade.findAll();
        for (Iterator<Nflplayer> it = players.iterator(); it.hasNext();) {
            Nflplayer player = it.next();
            if (!isAllowedPosition(player.getPosition())) {
                System.err.println(player.getId());
                playerFacade.remove(player);
            }
        }
        System.err.println("Filtering players done!");
        return returnPage;
    }

    public String filterPlayerSeasonStatByPosition() {
        playerseasons = playerSeasonFacade.findAll();
        for (Iterator<Nflplayerseasonstat> it = playerseasons.iterator(); it.hasNext();) {
            Nflplayerseasonstat seasonstat = it.next();
            int playerId = seasonstat.getNflplayerseasonstatPK().getPlayerId();
            Nflplayer targetPlayer = playerFacade.find(playerId);
            if (targetPlayer == null || !isAllowedPosition(targetPlayer.getPosition())) {
                System.err.append("Remove Season Stat for :" + playerId);
                playerSeasonFacade.remove(seasonstat);
            }
        }
        return returnPage;
    }

    public String queryAllPlayersFromLocalDB() {
        players = playerFacade.findAll();
        return returnPage;
    }

    public String queryAllPlayers() throws IOException {
        players = new ArrayList<Nflplayer>();
        for (int i = 0; i < teams.size(); i++) {
            Nflteam team = teams.get(i);
            queryTeamPlayers(team.getKeyCode());
        }
        queryFreeAgentsPlayers();
        return returnPage;
    }

    private void getPlayersFromUrl(URL url) throws IOException {
        Document doc = request(url, "GET", null);
        if (players == null) {
            players = new ArrayList();
        }
        NodeList nodes = doc.getElementsByTagName("Player");
        for (int i = 0; i < nodes.getLength(); i++) {
            Element e = (Element) nodes.item(i);
            // Only get POSITIONS
            String pos = getTextAsName(e, "Position");
            if (!isAllowedPosition(pos)) {
                continue;
            }
            Nflplayer player = createNflplayerFromElement(e);
            players.add(player);
        }
    }

    public String queryTeamPlayers(String team) throws IOException {
        System.err.println("queryTeamPlayers:" + team);
        URL url = new URL(TESTURL + "/xml/Players/" + team + "?key=" + licensekey);
        getPlayersFromUrl(url);
        return returnPage;
    }

    private String queryFreeAgentsPlayers() throws IOException {
        System.err.println("queryFreeAgentsPlayers");
        URL url = new URL(TESTURL + "/xml/FreeAgents?key=" + licensekey);
        getPlayersFromUrl(url);
        return returnPage;
    }

    public String queryAllPlayersSeasonStatsByTeam() throws IOException, JAXBException {
        playerseasons = new ArrayList<Nflplayerseasonstat>();
        for (int i = 0; i < teams.size(); i++) {
            Nflteam team = teams.get(i);
            //http://test.nfldata.com/api.svc/xml/PlayerSeasonStatsByTeam/2011/ATL?key=c7fb0f65-ccb4-4965-bbb9-4cecd0890e10
            URL url = new URL(APIURL + "/xml/PlayerSeasonStatsByTeam/" + season + "/" + team.getKeyCode() + "?key=" + licensekey);
            System.err.println(url);
            Document doc = request(url, "GET", null);
            NodeList nodes = doc.getElementsByTagName("PlayerSeason");

            for (int j = 0; j < nodes.getLength(); j++) {
                Element element = (Element) nodes.item(j);
                Nflplayerseasonstat playerSeasonStat = createNflplayerSeasonStatFromElement(element);
                Integer id = getIntegerAsName((Element) element, "PlayerID");
                Integer season = getIntegerAsName(element, "Season");
                System.err.println("id: " + id + " season: " + season);
                playerSeasonStat.setNflplayerseasonstatPK(new NflplayerseasonstatPK(id, season));
                playerseasons.add(playerSeasonStat);
            }
        }
        return returnPage;
    }

    protected Nflplayer createNflplayerFromElement(Element e) throws IOException {
        Nflplayer player = new Nflplayer();
        player.setId(getIntegerAsName(e, "PlayerID"));
        player.setLastName(getTextAsName(e, "LastName"));
        player.setFirstName(getTextAsName(e, "FirstName"));
        player.setAge(getIntegerAsName(e, "Age"));
        player.setNumber(getIntegerAsName(e, "Number"));
        player.setPhotoURL(getTextAsName(e, "PhotoUrl"));
        player.setPosition(getTextAsName(e, "Position"));
        player.setStatus(getTextAsName(e, "Status"));
        player.setActive(getBooleanAsName(e, "Active"));
        player.setAge(getIntegerAsName(e, "Age"));
        try {
            player.setBirthDate(dateFormat.parse(getTextAsName(e, "BirthDate")));
        } catch (ParseException ex) {
            Logger.getLogger(Crowler.class.getName()).log(Level.SEVERE, null, ex);
        }
        player.setHighSchool(getTextAsName(e, "HighSchool"));
        player.setCollege(getTextAsName(e, "College"));
        player.setByeweek(getIntegerAsName(e, "ByeWeek"));
        player.setHeight(getTextAsName(e, "Height"));
        player.setWeight(Float.parseFloat(getTextAsName(e, "Weight")));
        player.setExperienceYears(getIntegerAsName(e, "Experience"));
        System.err.println(player.getId());
        return player;
    }

    private Nflteam createNflteamFromElement(Element element) {
        Nflteam team = null;

//        JAXBContext jc;
//        Unmarshaller unmarshaller;

//        try {
//            jc = JAXBContext.newInstance(Nflteam.class);
//            unmarshaller = jc.createUnmarshaller();
//            team = (Nflteam) unmarshaller.unmarshal(element);
//        } catch (JAXBException ex) {
//            Logger.getLogger(Crowler.class.getName()).log(Level.SEVERE, null, ex);
//        }

        //team.setId(Integer.getInteger(getTextAsName(element, "id")));
        team = new Nflteam();
        team.setMascot(getTextAsName(element, "Name"));
        team.setHometown(getTextAsName(element, "City"));
        team.setFullname(getTextAsName(element, "Fullname"));
        team.setKeyCode(getTextAsName(element, "Key"));
        team.setDivision(getTextAsName(element, "Division"));
        team.setConference(getTextAsName(element, "Conference"));
        return team;
    }

    private Nflplayerseasonstat createNflplayerSeasonStatFromElement(Element element) throws JAXBException {

        Nflplayerseasonstat nflPlayerSeason = (Nflplayerseasonstat) unmarshallXMLToObject(element, Nflplayerseasonstat.class);
        System.err.println(nflPlayerSeason);
        return nflPlayerSeason;
    }

    /**
     * To set XmlElement to entity class REGEXP (public)(\s\w*\s)(get)(\w+) //
     * search
     *
     * @XmlElement(name="$4") \n$1$2$3$4 // replace
     */
    public String putTeamsIntoDB() {
        Nflteam previousTeam = null;
        for (Iterator<Nflteam> it = teams.iterator(); it.hasNext();) {
            Nflteam eachTeam = it.next();
            if (eachTeam == null) {
                System.err.println(previousTeam);
                continue;
            } else {
                System.err.println(eachTeam.getKeyCode());
                teamFacade.create(eachTeam);
                previousTeam = eachTeam;
            }
        }
        return returnPage;
    }

    public String putPlayersIntoDB() {
        Nflplayer previousPlayer = null;
        for (Iterator<Nflplayer> it = players.iterator(); it.hasNext();) {
            Nflplayer eachPlayer = it.next();
            if (eachPlayer == null) {
                System.err.println(previousPlayer);
                continue;
            } else {
                System.err.println(eachPlayer.getLastName());
                playerFacade.create(eachPlayer);
                previousPlayer = eachPlayer;
            }
        }
        return returnPage;
    }

    public String putPlayerSeasonStatsIntoDB() {
        Nflplayerseasonstat previousPlayer = null;
        for (Iterator<Nflplayerseasonstat> it = playerseasons.iterator(); it.hasNext();) {
            Nflplayerseasonstat eachPlayer = it.next();
            if (eachPlayer == null) {
                System.err.println(previousPlayer);
                continue;
            } else {
                System.err.println(eachPlayer.getNflplayerseasonstatPK().getPlayerId());
                playerSeasonFacade.create(eachPlayer);
                previousPlayer = eachPlayer;
            }
        }
        return returnPage;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getSeason() {
        return season;
    }

    public void setSeason(String season) {
        this.season = season;
    }

    public List<entities.Nflteam> getTeams() throws IOException {
        return teams;
    }

    public void setTeams(List teams) {
        this.teams = teams;
    }

    public List<entities.Nflplayer> getPlayers() throws IOException {
        return players;
    }

    public void setPlayers(List<entities.Nflplayer> players) {
        this.players = players;
    }

    public List<Nflplayerseasonstat> getPlayerseasons() {
        return playerseasons;
    }

    public void setPlayerseasons(List<Nflplayerseasonstat> playerseasons) {
        this.playerseasons = playerseasons;
    }
}